import { OmnichannelAnalytics } from '@rocket.chat/core-services';
import { Users } from '@rocket.chat/models';
import {
	isGETDashboardTotalizerParams,
	isGETDashboardsAgentStatusParams,
	isGETLivechatAnalyticsDashboardsChartDataParams,
	validateUnauthorizedErrorResponse,
	validateForbiddenErrorResponse,
	GETLivechatAnalyticsDashboardsChartDataSuccessSchema,
} from '@rocket.chat/rest-typings';

import { API } from '../../../../api/server';
import type { ExtractRoutesFromAPI } from '../../../../api/server/ApiClass';
import {
	getProductivityMetricsAsyncCached,
	getConversationsMetricsAsyncCached,
	getAgentsProductivityMetricsAsyncCached,
	getChatsMetricsAsyncCached,
	findAllChatsStatusAsyncCached,
	findAllChatMetricsByAgentAsyncCached,
	findAllAgentsStatusAsyncCached,
	findAllChatMetricsByDepartmentAsyncCached,
	findAllResponseTimeMetricsAsyncCached,
} from '../../../server/lib/analytics/dashboards';

API.v1.addRoute(
	'livechat/analytics/dashboards/conversation-totalizers',
	{
		authRequired: true,
		permissionsRequired: ['view-livechat-manager'],
		validateParams: isGETDashboardTotalizerParams,
	},
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}

			const user = await Users.findOneById(this.userId, { projection: { utcOffset: 1, language: 1 } });
			if (!user) {
				return API.v1.failure('User not found');
			}

			const totalizers = await getConversationsMetricsAsyncCached({ start, end, departmentId, user });
			return API.v1.success(totalizers);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/agents-productivity-totalizers',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}

			const user = await Users.findOneById(this.userId, { projection: { utcOffset: 1, language: 1 } });
			if (!user) {
				return API.v1.failure('User not found');
			}

			const totalizers = await getAgentsProductivityMetricsAsyncCached({ start, end, departmentId, user });
			return API.v1.success(totalizers);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/chats-totalizers',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}
			const startDate = new Date(start);

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}
			const endDate = new Date(end);

			const totalizers = await getChatsMetricsAsyncCached({ start: startDate, end: endDate, departmentId });
			return API.v1.success(totalizers);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/productivity-totalizers',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}

			const user = await Users.findOneById(this.userId, { projection: { utcOffset: 1, language: 1 } });
			if (!user) {
				return API.v1.failure('User not found');
			}

			const totalizers = await getProductivityMetricsAsyncCached({ start, end, departmentId, user });

			return API.v1.success(totalizers);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/charts/chats',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}
			const startDate = new Date(start);

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}
			const endDate = new Date(end);

			const result = await findAllChatsStatusAsyncCached({ start: startDate, end: endDate, departmentId });

			return API.v1.success(result);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/charts/chats-per-agent',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}
			const startDate = new Date(start);

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}
			const endDate = new Date(end);
			const result = await findAllChatMetricsByAgentAsyncCached({ start: startDate, end: endDate, departmentId });

			return API.v1.success(result);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/charts/agents-status',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardsAgentStatusParams },
	{
		async get() {
			const { departmentId } = this.queryParams;

			const result = await findAllAgentsStatusAsyncCached({ departmentId });

			return API.v1.success(result);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/charts/chats-per-department',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}
			const startDate = new Date(start);

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}
			const endDate = new Date(end);

			const result = (await findAllChatMetricsByDepartmentAsyncCached({ start: startDate, end: endDate, departmentId })) as {
				[k: string]: { open: number; closed: number };
			};

			return API.v1.success(result);
		},
	},
);

API.v1.addRoute(
	'livechat/analytics/dashboards/charts/timings',
	{ authRequired: true, permissionsRequired: ['view-livechat-manager'], validateParams: isGETDashboardTotalizerParams },
	{
		async get() {
			const { start, end } = this.queryParams;
			const { departmentId } = this.queryParams;

			if (isNaN(Date.parse(start))) {
				return API.v1.failure('The "start" query parameter must be a valid date.');
			}
			const startDate = new Date(start);

			if (isNaN(Date.parse(end))) {
				return API.v1.failure('The "end" query parameter must be a valid date.');
			}
			const endDate = new Date(end);

			const result = await findAllResponseTimeMetricsAsyncCached({ start: startDate, end: endDate, departmentId });

			return API.v1.success(result);
		},
	},
);

const livechatAnalyticsEndpoints = API.v1.get(
	'livechat/analytics/dashboards/charts-data',
	{
		response: {
			200: GETLivechatAnalyticsDashboardsChartDataSuccessSchema,
			401: validateUnauthorizedErrorResponse,
			403: validateForbiddenErrorResponse,
		},
		authRequired: true,
		permissionsRequired: ['view-livechat-manager'],
		query: isGETLivechatAnalyticsDashboardsChartDataParams,
	},
	async function action() {
		const { chartName, start, end, departmentId } = this.queryParams;

		const chartData = await OmnichannelAnalytics.getAnalyticsChartData({
			daterange: {
				from: start,
				to: end,
			},
			chartOptions: {
				name: chartName,
			},
			utcOffset: this.user.utcOffset,
			executedBy: this.user._id,
			departmentId,
		});

		if (!chartData) {
			return API.v1.success({
				chartLabel: chartName,
				dataLabels: [],
				dataPoints: [],
			});
		}

		return API.v1.success(chartData);
	},
);

type LivechatAnalyticsEndpoints = ExtractRoutesFromAPI<typeof livechatAnalyticsEndpoints>;

declare module '@rocket.chat/rest-typings' {
	// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
	interface Endpoints extends LivechatAnalyticsEndpoints {}
}
